#include <init/IDT.h>
#include <string.h>

/* Defines an IDT entry */
struct idt_entry
{
    _u16 base_lo;    		// offset bits 0..15
    _u16 selector;   		// a code segment selector in GDT or LDT
    _u8  zero;       		// unused, set to 0
    _u8  flags;      		// flags
    _u16 base_hi;    		// offset bits 16..31
} __attribute__((packed));

struct idt_ptr
{
    _u16 limit;
    _u32 base;
} __attribute__((packed));

/* Declare an IDT of 256 entries */ 
struct idt_entry idt[256];

struct idt_ptr idtp;

/* This exists in 'init.S', and is used to load IDT */
extern void idt_flush();

/* Set an entry in the IDT */
void idt_set_gate(_u8 num, _u32 base, _u16 selector, _u8 flags)
{
    idt[num].base_lo = (base & 0xFFFF);
    idt[num].base_hi = (base >> 16) & 0xFFFF;

    idt[num].selector = selector;
    idt[num].zero = 0;
    idt[num].flags = flags;
}

/* Installs the IDT */
void idt_install()
{
    idtp.limit = (sizeof (struct idt_entry) * 256) - 1;
    idtp.base = (_u32)&idt;

    /* Clear out the entire IDT, initializing it to zeros */
    memset(&idt, 0, sizeof(struct idt_entry) * 256);

    /* Points the processor's internal register to the new IDT */
    idt_flush();
}
